home *** CD-ROM | disk | FTP | other *** search
- /* SymbolTable.c */
- /*****************************************************************************/
- /* */
- /* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
- /* Copyright (C) 1994 Thomas R. Lawrence */
- /* */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2 of the License, or */
- /* (at your option) any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to the Free Software */
- /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* */
- /* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
- /* */
- /*****************************************************************************/
-
- #include "MiscInfo.h"
- #include "Audit.h"
- #include "Debug.h"
- #include "Definitions.h"
-
- #include "SymbolTable.h"
- #include "SymbolTableEntry.h"
- #include "TrashTracker.h"
- #include "Memory.h"
- #include "DataMunging.h"
-
-
- /* since we use bit masking, the hash table size must be a power of 2 */
- #define HASHTABLESIZE (1L << 10)
- #define HASHTABLEMASK (HASHTABLESIZE - 1)
-
-
- typedef struct SymbolHeadRec
- {
- long LexicalLevel;
- struct SymbolHeadRec** PreviousMetaAddress;
- struct SymbolHeadRec* Next; /* hash bucket link; also used on free list */
- SymbolRec* Symbol;
- struct SymbolHeadRec* LexicalLevelNext;
- } SymbolHeadRec;
-
-
- typedef struct LevelRec
- {
- struct LevelRec* OneScopeDown; /* also used on free list */
- SymbolHeadRec* ThisLevelList;
- } LevelRec;
-
-
- struct SymbolTableRec
- {
- long LexicalLevel;
- LevelRec* LevelStack;
- TrashTrackRec* Allocator;
-
- LevelRec* FreeLevelList;
- SymbolHeadRec* FreeSymbolHeadList;
-
- SymbolHeadRec* HashTable[HASHTABLESIZE];
- };
-
-
- /* create a new symbol table */
- SymbolTableRec* NewSymbolTable(struct TrashTrackRec* TrashTracker)
- {
- SymbolTableRec* SymbolTable;
- long Scan;
-
- SymbolTable = (SymbolTableRec*)AllocTrackedBlock(sizeof(SymbolTableRec),TrashTracker);
- if (SymbolTable == NIL)
- {
- return NIL;
- }
- SetTag(SymbolTable,"SymbolTableRec");
-
- for (Scan = 0; Scan < HASHTABLESIZE; Scan += 1)
- {
- SymbolTable->HashTable[Scan] = NIL;
- }
-
- SymbolTable->FreeLevelList = NIL;
- SymbolTable->FreeSymbolHeadList = NIL;
-
- SymbolTable->LexicalLevel = 0;
- SymbolTable->Allocator = TrashTracker;
-
- SymbolTable->LevelStack = (LevelRec*)AllocTrackedBlock(sizeof(LevelRec),TrashTracker);
- if (SymbolTable->LevelStack == NIL)
- {
- return NIL;
- }
- SetTag(SymbolTable->LevelStack,"SymbolTableRec: LevelStackRec");
-
- SymbolTable->LevelStack->OneScopeDown = NIL;
- SymbolTable->LevelStack->ThisLevelList = NIL;
-
- return SymbolTable;
- }
-
-
- /* create a new symbol table level */
- MyBoolean IncrementSymbolTableLevel(SymbolTableRec* SymbolTable)
- {
- LevelRec* NewLevel;
-
- CheckPtrExistence(SymbolTable);
-
- if (SymbolTable->FreeLevelList != NIL)
- {
- NewLevel = SymbolTable->FreeLevelList;
- SymbolTable->FreeLevelList = SymbolTable->FreeLevelList->OneScopeDown;
- }
- else
- {
- NewLevel = (LevelRec*)AllocTrackedBlock(sizeof(LevelRec),SymbolTable->Allocator);
- if (NewLevel == NIL)
- {
- return False;
- }
- }
-
- NewLevel->OneScopeDown = SymbolTable->LevelStack;
- NewLevel->ThisLevelList = NIL;
-
- SymbolTable->LevelStack = NewLevel;
- SymbolTable->LexicalLevel += 1;
-
- return True;
- }
-
-
- /* drop the current symbol table lexical level */
- void DecrementSymbolTableLevel(SymbolTableRec* SymbolTable)
- {
- SymbolHeadRec* Scan;
-
- CheckPtrExistence(SymbolTable);
- ERROR(SymbolTable->LexicalLevel == 0,PRERR(ForceAbort,
- "DecrementSymbolTableLevel: at outer level -- can't drop"));
-
- /* this list has been built in the order symbols were added. so when we delink */
- /* them, it's in the reverse order. by induction, each element being deleted */
- /* is at the head of it's hash bucket. this is why we can use the metapointer. */
- Scan = SymbolTable->LevelStack->ThisLevelList;
- while (Scan != NIL)
- {
- SymbolHeadRec* Temp;
-
- /* save the first node we are dropping */
- Temp = Scan;
-
- /* delete node from current level's list */
- Scan = Scan->LexicalLevelNext;
-
- /* delink node from it's bucket */
- *(Temp->PreviousMetaAddress) = Temp->Next;
-
- /* stick temp onto the free list */
- Temp->Next = SymbolTable->FreeSymbolHeadList;
- SymbolTable->FreeSymbolHeadList = Temp;
- }
-
- /* drop the stack record */
- SymbolTable->LevelStack = SymbolTable->LevelStack->OneScopeDown;
- }
-
-
- /* add symbol table entry to the symbol table. returns a result code */
- AddSymbolType AddSymbolToTable(SymbolTableRec* SymbolTable,
- struct SymbolRec* SymbolToAdd)
- {
- SymbolHeadRec* SymbolHead;
- long HashIndex;
- char* SymbolName;
-
- CheckPtrExistence(SymbolTable);
- CheckPtrExistence(SymbolToAdd);
-
- /* find out where in the hash table it belongs */
- HashIndex = HASHTABLEMASK & GetSymbolHashValue(SymbolToAdd);
-
- /* see if symbol already exists */
- SymbolName = GetSymbolName(SymbolToAdd);
- CheckPtrExistence(SymbolName);
- /* it must be at this level only */
- SymbolHead = SymbolTable->HashTable[HashIndex];
- while ((SymbolHead != NIL) && (SymbolHead->LexicalLevel == SymbolTable->LexicalLevel))
- {
- char* OtherSymbolName;
-
- OtherSymbolName = GetSymbolName(SymbolHead->Symbol);
- if (PtrSize(OtherSymbolName) == PtrSize(SymbolName))
- {
- if (MemEqu(OtherSymbolName,SymbolName,PtrSize(SymbolName)))
- {
- return eAddSymbolAlreadyExists;
- }
- }
- SymbolHead = SymbolHead->Next;
- }
-
- if (SymbolTable->FreeSymbolHeadList != NIL)
- {
- SymbolHead = SymbolTable->FreeSymbolHeadList;
- SymbolTable->FreeSymbolHeadList = SymbolTable->FreeSymbolHeadList->Next;
- }
- else
- {
- SymbolHead = (SymbolHeadRec*)AllocTrackedBlock(sizeof(SymbolHeadRec),
- SymbolTable->Allocator);
- if (SymbolHead == NIL)
- {
- return eAddSymbolNoMemory;
- }
- SetTag(SymbolHead,"SymbolHeadRec");
- }
-
- /* set the meta reference for delinking */
- SymbolHead->PreviousMetaAddress = &(SymbolTable->HashTable[HashIndex]);
-
- /* add the thing to the hash chain (at the head) */
- SymbolHead->Next = SymbolTable->HashTable[HashIndex];
- SymbolTable->HashTable[HashIndex] = SymbolHead;
-
- /* put the symbol in the record */
- SymbolHead->Symbol = SymbolToAdd;
-
- /* link it into the lexical level thing */
- SymbolHead->LexicalLevelNext = SymbolTable->LevelStack->ThisLevelList;
- SymbolTable->LevelStack->ThisLevelList = SymbolHead;
-
- /* set the lexical level */
- SymbolHead->LexicalLevel = SymbolTable->LexicalLevel;
-
- return eAddSymbolNoErr;
- }
-
-
- /* get a symbol from the symboldflksakdo table */
- /* it returns NIL if the entry was not found. */
- struct SymbolRec* GetSymbolFromTable(SymbolTableRec* SymbolTable, char* NameString,
- long NameStringLength)
- {
- SymbolHeadRec* SymbolHead;
-
- CheckPtrExistence(SymbolTable);
-
- SymbolHead = SymbolTable->HashTable[HASHTABLEMASK
- & UseSymbolTableHash(NameString,NameStringLength)];
- while (SymbolHead != NIL)
- {
- char* OtherSymbolName;
-
- OtherSymbolName = GetSymbolName(SymbolHead->Symbol);
- if (PtrSize(OtherSymbolName) == NameStringLength)
- {
- if (MemEqu(OtherSymbolName,NameString,NameStringLength))
- {
- /* found it! */
- return SymbolHead->Symbol;
- }
- }
- SymbolHead = SymbolHead->Next;
- }
-
- return NIL;
- }
-